''' 目标函数部分 '''

# 教师满意度 + 学生满意度 综合考虑
# 教室利用率
# 师生换教学楼距离
import statistics

import numpy as np

import config

'''添加单双周和起始周  SPF   2024.5.9'''


# def target_fun(schemesList, buildings_dis, len_students, len_teachers):
def target_fun(RTmatrix_filled, STmatrix_filled, TTmatrix_filled, buildings_dis, len_students, len_teachers):
    # 1.计算学生满意度和学生满意度， 2.计算教室利用率  3. 计算上课距离最近
    # 将每个方案的两个指标添加到适应度值列表中，列表为一个二维列表
    s_var_arr = []
    t_var_arr = []
    room_vacancy_rate_arr = []
    s_dis_arr = []
    t_dis_arr = []
    target = []
    # 定义每天的天数和周期数
    num_days = config.num_days
    periods_per_day = config.periods_per_day
    teacher_weight = config.teacher_weight
    student_weight = config.student_weight

    # 三个目标函数加入单双周考虑
    for ST in STmatrix_filled:
        # 这个排课方案中的学生样本方差
        variance_s = 0
        # 学生周距离
        week_s_dis = 0
        for s_t in ST:
            for s in s_t:
                # 周一维数组
                week_jieci = [0] * num_days
                # 初始化学生同一天上课的（day+jieci+building）
                student_course_time = []
                timeslices = np.where(np.array(s, object) != "")[0]
                for timeslice in timeslices:
                    day_index = timeslice // periods_per_day
                    jieci = (timeslice % periods_per_day) + 1
                    week_jieci[day_index] += 1
                    student_course_time.append((day_index, jieci, s[timeslice][1][2]))
                # 计算每个学生1-2，3-4大节的距离
                if any(count >= 2 for count in week_jieci):
                    for time_building in student_course_time:
                        for t_b in student_course_time:
                            if t_b is not time_building:
                                if time_building[0] == t_b[0] and time_building[1] != 5 and t_b[1] != 5:
                                    if abs(time_building[1] - t_b[1]) == 1 and (
                                            ((time_building[1] in [1, 2]) and (t_b[1] in [1, 2])) or (
                                            (time_building[1] in [3, 4]) and (t_b[1] in [3, 4]))):
                                        for dis in buildings_dis:
                                            if time_building[2] in dis and t_b[2] in dis:
                                                week_s_dis += dis[2]
                                                break
                variance_s += statistics.variance(week_jieci)
        s_var_arr.append(variance_s)
        s_dis_arr.append(week_s_dis)

    for TT in TTmatrix_filled:
        # 这个排课方案中的教师样本方差
        variance_t = 0
        # 教师周距离
        week_t_dis = 0
        for t_t in TT:
            for t in t_t:
                # 周节次二维结构
                week_jieci = [0] * num_days
                # 初始化学生同一天上课的（day+jieci+building）
                teacher_course_time = []
                timeslices = np.where(np.array(t, object) != "")[0]
                for timeslice in timeslices:
                    day_index = timeslice // periods_per_day
                    jieci = (timeslice % periods_per_day) + 1
                    week_jieci[day_index] += 1
                    teacher_course_time.append((day_index, jieci, t[timeslice][1][2]))
                # 计算每个学生1-2，3-4大节的距离
                if any(count >= 2 for count in week_jieci):
                    for time_building in teacher_course_time:
                        for t_b in teacher_course_time:
                            if t_b is not time_building:
                                if time_building[0] == t_b[0] and time_building[1] != 5 and t_b[1] != 5:
                                    if abs(time_building[1] - t_b[1]) == 1 and (
                                            (time_building[1] == 1 or t_b[1] == 1) and (
                                            time_building[1] == 2 or t_b[1] == 2) or (
                                                    time_building[1] == 3 or t_b[1] == 3) and (
                                                    time_building[1] == 4 or t_b[1] == 4)):
                                        for dis in buildings_dis:
                                            if time_building[2] in dis and t_b[2] in dis:
                                                week_t_dis += dis[2]
                                                break
                variance_t += statistics.variance(week_jieci)
        t_var_arr.append(variance_t)
        t_dis_arr.append(week_t_dis)

    # 教室空闲率
    for RT in RTmatrix_filled:
        empty_room = 0
        total_room = 0

        for r_t in RT:
            for r in r_t:
                t_indexs = np.where(np.array(r, object) != "")[0]
                for t_index in t_indexs:
                    empty_room += (r[t_index][1] - r[t_index][2])
                    total_room += r[t_index][1]
        room_vacancy_rate = round(empty_room / total_room, 2)
        room_vacancy_rate_arr.append(room_vacancy_rate)
    for i in range(config.particals):
        t_s_satisfaction = round(t_var_arr[i] * teacher_weight + s_var_arr[i] * student_weight, 2)
        t_s_dis = round(t_dis_arr[i] / len_teachers * teacher_weight + s_dis_arr[i] / len_students * student_weight, 2)
        target.append([t_s_satisfaction, room_vacancy_rate_arr[i], t_s_dis])
    return target
